#pragma once

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdarg>
#include <ctime>

const int MAX_LEN = 1024;

enum LOG_ENUM
{
    INFO = 1,
    WARNING,
    ERROR,
    FATAL
};

FILE* defaultFile = stdout;
LOG_ENUM defaultLevel = INFO;

#define Log(Level, format, ...) log(Level, __LINE__, __FILE__, format, ##__VA_ARGS__)

void setLogFile(const char* filename)
{
    FILE* tmp = fopen(filename, "a");
    if(tmp == NULL)
    {
        return;
    }
    defaultFile = tmp;
}

void setLogLevel(LOG_ENUM level)
{
    defaultLevel = level;
}

const char* numToStr(LOG_ENUM num)
{
    switch (num)
    {
    case INFO: return "INFO";
    case WARNING: return "WARNING";
    case ERROR: return "ERROR";
    case FATAL: return "FATAL";
    default:
        break;
    }
    return nullptr;
}

void log(LOG_ENUM Level, int line, const char* file, const char* format, ...)
{
    if(Level < defaultLevel) return;
    char buffer[MAX_LEN] = { 0 };
    va_list ap;
    va_start(ap, format);
    vsnprintf(buffer, MAX_LEN - 1, format, ap);
    va_end(ap);
    time_t nowtime;
    time(&nowtime);
    tm* p = localtime(&nowtime);
    fprintf(defaultFile, "%04d-%02d-%02d %02d:%02d:%02d "        \
    , p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
    fprintf(defaultFile, "| %-7s | %s   [%s]<%d>\n", numToStr(Level), buffer, file, line);
}
